home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 001-025 / disk_022 / lemacs / random.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  17KB  |  589 lines

  1. /*
  2.  * This file contains the command processing functions for a number of random
  3.  * commands. There is no functional grouping here, for sure.
  4.  */
  5.  
  6. #include        <stdio.h>
  7. #include    "estruct.h"
  8. #include        "edef.h"
  9.  
  10. int     tabsize;                        /* Tab size (0: use real tabs)  */
  11.  
  12. /*
  13.  * Set fill column to n.
  14.  */
  15. setfillcol(f, n)
  16. {
  17.         fillcol = n;
  18.     mlwrite("[Fill column is %d]",n);
  19.         return(TRUE);
  20. }
  21.  
  22. /*
  23.  * Display the current position of the cursor, in origin 1 X-Y coordinates,
  24.  * the character that is under the cursor (in octal), and the fraction of the
  25.  * text that is before the cursor. The displayed column is not the current
  26.  * column, but the column that would be used on an infinite width display.
  27.  * Normally this is bound to "C-X =".
  28.  */
  29. showcpos(f, n)
  30. {
  31.         register LINE   *clp;
  32.         register long   nch;
  33.         register int    cbo;
  34.         register long   nbc;
  35.         register int    cac;
  36.         register int    ratio;
  37.         register int    col;
  38.  
  39.         clp = lforw(curbp->b_linep);            /* Grovel the data.     */
  40.         cbo = 0;
  41.         nch = 0;
  42.         for (;;) {
  43.                 if (clp==curwp->w_dotp && cbo==curwp->w_doto) {
  44.                         nbc = nch;
  45.                         if (cbo == llength(clp))
  46.                                 cac = '\n';
  47.                         else
  48.                                 cac = lgetc(clp, cbo);
  49.                 }
  50.                 if (cbo == llength(clp)) {
  51.                         if (clp == curbp->b_linep)
  52.                                 break;
  53.                         clp = lforw(clp);
  54.                         cbo = 0;
  55.                 } else
  56.                         ++cbo;
  57.                 ++nch;
  58.         }
  59.         col = getccol(FALSE);                   /* Get real column.     */
  60.         ratio = 0;                              /* Ratio before dot.    */
  61.         if (nch != 0)
  62.                 ratio = (100L*nbc) / nch;
  63.         mlwrite("X=%d Y=%d CH=0x%x .=%D (%d%% of %D)",
  64.                 col+1, currow+1, cac, nbc, ratio, nch);
  65.         return (TRUE);
  66. }
  67.  
  68. /*
  69.  * Return current column.  Stop at first non-blank given TRUE argument.
  70.  */
  71. getccol(bflg)
  72. int bflg;
  73. {
  74.         register int c, i, col;
  75.         col = 0;
  76.         for (i=0; i<curwp->w_doto; ++i) {
  77.                 c = lgetc(curwp->w_dotp, i);
  78.                 if (c!=' ' && c!='\t' && bflg)
  79.                         break;
  80.                 if (c == '\t')
  81.                         col |= 0x07;
  82.                 else if (c<0x20 || c==0x7F)
  83.                         ++col;
  84.                 ++col;
  85.         }
  86.         return(col);
  87. }
  88.  
  89. /*
  90.  * Twiddle the two characters on either side of dot. If dot is at the end of
  91.  * the line twiddle the two characters before it. Return with an error if dot
  92.  * is at the beginning of line; it seems to be a bit pointless to make this
  93.  * work. This fixes up a very common typo with a single stroke. Normally bound
  94.  * to "C-T". This always works within a line, so "WFEDIT" is good enough.
  95.  */
  96. twiddle(f, n)
  97. {
  98.         register LINE   *dotp;
  99.         register int    doto;
  100.         register int    cl;
  101.         register int    cr;
  102.  
  103.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  104.         return(rdonly());    /* we are in read only mode    */
  105.         dotp = curwp->w_dotp;
  106.         doto = curwp->w_doto;
  107.         if (doto==llength(dotp) && --doto<0)
  108.                 return (FALSE);
  109.         cr = lgetc(dotp, doto);
  110.         if (--doto < 0)
  111.                 return (FALSE);
  112.         cl = lgetc(dotp, doto);
  113.         lputc(dotp, doto+0, cr);
  114.         lputc(dotp, doto+1, cl);
  115.         lchange(WFEDIT);
  116.         return (TRUE);
  117. }
  118.  
  119. /*
  120.  * Quote the next character, and insert it into the buffer. All the characters
  121.  * are taken literally, with the exception of the newline, which always has
  122.  * its line splitting meaning. The character is always read, even if it is
  123.  * inserted 0 times, for regularity. Bound to "C-Q"
  124.  */
  125. quote(f, n)
  126. {
  127.         register int    s;
  128.         register int    c;
  129.  
  130.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  131.         return(rdonly());    /* we are in read only mode    */
  132.         c = (*term.t_getchar)();
  133.         if (n < 0)
  134.                 return (FALSE);
  135.         if (n == 0)
  136.                 return (TRUE);
  137.         if (c == '\n') {
  138.                 do {
  139.                         s = lnewline();
  140.                 } while (s==TRUE && --n);
  141.                 return (s);
  142.         }
  143.         return (linsert(n, c));
  144. }
  145.  
  146. /*
  147.  * Set tab size if given non-default argument (n <> 1).  Otherwise, insert a
  148.  * tab into file.  If given argument, n, of zero, change to true tabs.
  149.  * If n > 1, simulate tab stop every n-characters using spaces. This has to be
  150.  * done in this slightly funny way because the tab (in ASCII) has been turned
  151.  * into "C-I" (in 10 bit code) already. Bound to "C-I".
  152.  */
  153. tab(f, n)
  154. {
  155.         if (n < 0)
  156.                 return (FALSE);
  157.         if (n == 0 || n > 1) {
  158.                 tabsize = n;
  159.                 return(TRUE);
  160.         }
  161.         if (! tabsize)
  162.                 return(linsert(1, '\t'));
  163.         return(linsert(tabsize - (getccol(FALSE) % tabsize), ' '));
  164. }
  165.  
  166. /*
  167.  * Open up some blank space. The basic plan is to insert a bunch of newlines,
  168.  * and then back up over them. Everything is done by the subcommand
  169.  * procerssors. They even handle the looping. Normally this is bound to "C-O".
  170.  */
  171. openline(f, n)
  172. {
  173.         register int    i;
  174.         register int    s;
  175.  
  176.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  177.         return(rdonly());    /* we are in read only mode    */
  178.         if (n < 0)
  179.                 return (FALSE);
  180.         if (n == 0)
  181.                 return (TRUE);
  182.         i = n;                                  /* Insert newlines.     */
  183.         do {
  184.                 s = lnewline();
  185.         } while (s==TRUE && --i);
  186.         if (s == TRUE)                          /* Then back up overtop */
  187.                 s = backchar(f, n);             /* of them all.         */
  188.         return (s);
  189. }
  190.  
  191. /*
  192.  * Insert a newline. Bound to "C-M". If we are in CMODE, do automatic
  193.  * indentation as specified.
  194.  */
  195. newline(f, n)
  196. {
  197.     register int    s;
  198.  
  199.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  200.         return(rdonly());    /* we are in read only mode    */
  201.     if (n < 0)
  202.         return (FALSE);
  203.  
  204.     /* if we are in C mode and this is a default <NL> */
  205.     if (n == 1 && (curbp->b_mode & MDCMOD) &&
  206.         curwp->w_dotp != curbp->b_linep)
  207.         return(cinsert());
  208.  
  209.     /* insert some lines */
  210.     while (n--) {
  211.         if ((s=lnewline()) != TRUE)
  212.             return (s);
  213.     }
  214.     return (TRUE);
  215. }
  216.  
  217. cinsert()    /* insert a newline and indentation for C */
  218.  
  219. {
  220.     register char *cptr;    /* string pointer into text to copy */
  221.     register int tptr;    /* index to scan into line */
  222.     register int bracef;    /* was there a brace at the end of line? */
  223.     register int i;
  224.     char ichar[NSTRING];    /* buffer to hold indent of last line */
  225.  
  226.     /* grab a pointer to text to copy indentation from */
  227.     cptr = &curwp->w_dotp->l_text[0];
  228.  
  229.     /* check for a brace */
  230.     tptr = curwp->w_doto - 1;
  231.     bracef = (cptr[tptr] == '{');
  232.  
  233.     /* save the indent of the previous line */
  234.     i = 0;
  235.     while ((i < tptr) && (cptr[i] == ' ' || cptr[i] == '\t')
  236.         && (i < NSTRING - 1)) {
  237.         ichar[i] = cptr[i];
  238.         ++i;
  239.     }
  240.     ichar[i] = 0;        /* terminate it */
  241.  
  242.     /* put in the newline */
  243.     if (lnewline() == FALSE)
  244.         return(FALSE);
  245.  
  246.     /* and the saved indentation */
  247.     i = 0;
  248.     while (ichar[i])
  249.         linsert(1, ichar[i++]);
  250.  
  251.     /* and one more tab for a brace */
  252.     if (bracef)
  253.         tab(FALSE, 1);
  254.  
  255.     return(TRUE);
  256. }
  257.  
  258. insbrace(n, c)    /* insert a brace into the text here...we are in CMODE */
  259.  
  260. int n;    /* repeat count */
  261. int c;    /* brace to insert (always { for now) */
  262.  
  263. {
  264.     register int ch;    /* last character before input */
  265.     register int i;
  266.     register int target;    /* column brace should go after */
  267.  
  268.     /* if we are at the begining of the line, no go */
  269.     if (curwp->w_doto == 0)
  270.         return(linsert(n,c));
  271.         
  272.     /* scan to see if all space before this is white space */
  273.     for (i = curwp->w_doto - 1; i >= 0; --i) {
  274.         ch = lgetc(curwp->w_dotp, i);
  275.         if (ch != ' ' && ch != '\t')
  276.             return(linsert(n, c));
  277.     }
  278.  
  279.     /* delete back first */
  280.     target = getccol(FALSE);    /* calc where we will delete to */
  281.     target -= 1;
  282.     target -= target % (tabsize == 0 ? 8 : tabsize);
  283.     while (getccol(FALSE) > target)
  284.         backdel(FALSE, 1);
  285.  
  286.     /* and insert the required brace(s) */
  287.     return(linsert(n, c));
  288. }
  289.  
  290. inspound()    /* insert a # into the text here...we are in CMODE */
  291.  
  292. {
  293.     register int ch;    /* last character before input */
  294.     register int i;
  295.  
  296.     /* if we are at the begining of the line, no go */
  297.     if (curwp->w_doto == 0)
  298.         return(linsert(1,'#'));
  299.         
  300.     /* scan to see if all space before this is white space */
  301.     for (i = curwp->w_doto - 1; i >= 0; --i) {
  302.         ch = lgetc(curwp->w_dotp, i);
  303.         if (ch != ' ' && ch != '\t')
  304.             return(linsert(1, '#'));
  305.     }
  306.  
  307.     /* delete back first */
  308.     while (getccol(FALSE) > 1)
  309.         backdel(FALSE, 1);
  310.  
  311.     /* and insert the required pound */
  312.     return(linsert(1, '#'));
  313. }
  314.  
  315. /*
  316.  * Delete blank lines around dot. What this command does depends if dot is
  317.  * sitting on a blank line. If dot is sitting on a blank line, this command
  318.  * deletes all the blank lines above and below the current line. If it is
  319.  * sitting on a non blank line then it deletes all of the blank lines after
  320.  * the line. Normally this command is bound to "C-X C-O". Any argument is
  321.  * ignored.
  322.  */
  323. deblank(f, n)
  324. {
  325.         register LINE   *lp1;
  326.         register LINE   *lp2;
  327.         register int    nld;
  328.  
  329.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  330.         return(rdonly());    /* we are in read only mode    */
  331.         lp1 = curwp->w_dotp;
  332.         while (llength(lp1)==0 && (lp2=lback(lp1))!=curbp->b_linep)
  333.                 lp1 = lp2;
  334.         lp2 = lp1;
  335.         nld = 0;
  336.         while ((lp2=lforw(lp2))!=curbp->b_linep && llength(lp2)==0)
  337.                 ++nld;
  338.         if (nld == 0)
  339.                 return (TRUE);
  340.         curwp->w_dotp = lforw(lp1);
  341.         curwp->w_doto = 0;
  342.         return (ldelete(nld));
  343. }
  344.  
  345. /*
  346.  * Insert a newline, then enough tabs and spaces to duplicate the indentation
  347.  * of the previous line. Assumes tabs are every eight characters. Quite simple.
  348.  * Figure out the indentation of the current line. Insert a newline by calling
  349.  * the standard routine. Insert the indentation by inserting the right number
  350.  * of tabs and spaces. Return TRUE if all ok. Return FALSE if one of the
  351.  * subcomands failed. Normally bound to "C-J".
  352.  */
  353. indent(f, n)
  354. {
  355.         register int    nicol;
  356.         register int    c;
  357.         register int    i;
  358.  
  359.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  360.         return(rdonly());    /* we are in read only mode    */
  361.         if (n < 0)
  362.                 return (FALSE);
  363.         while (n--) {
  364.                 nicol = 0;
  365.                 for (i=0; i<llength(curwp->w_dotp); ++i) {
  366.                         c = lgetc(curwp->w_dotp, i);
  367.                         if (c!=' ' && c!='\t')
  368.                                 break;
  369.                         if (c == '\t')
  370.                                 nicol |= 0x07;
  371.                         ++nicol;
  372.                 }
  373.                 if (lnewline() == FALSE
  374.                 || ((i=nicol/8)!=0 && linsert(i, '\t')==FALSE)
  375.                 || ((i=nicol%8)!=0 && linsert(i,  ' ')==FALSE))
  376.                         return (FALSE);
  377.         }
  378.         return (TRUE);
  379. }
  380.  
  381. /*
  382.  * Delete forward. This is real easy, because the basic delete routine does
  383.  * all of the work. Watches for negative arguments, and does the right thing.
  384.  * If any argument is present, it kills rather than deletes, to prevent loss
  385.  * of text if typed with a big argument. Normally bound to "C-D".
  386.  */
  387. forwdel(f, n)
  388. {
  389.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  390.         return(rdonly());    /* we are in read only mode    */
  391.         if (n < 0)
  392.                 return (backdel(f, -n));
  393.         if (f != FALSE) {                       /* Really a kill.       */
  394.                 if ((lastflag&CFKILL) == 0)
  395.                         kdelete();
  396.                 thisflag |= CFKILL;
  397.         }
  398.         return (ldelete(n, f));
  399. }
  400.  
  401. /*
  402.  * Delete backwards. This is quite easy too, because it's all done with other
  403.  * functions. Just move the cursor back, and delete forwards. Like delete
  404.  * forward, this actually does a kill if presented with an argument. Bound to
  405.  * both "RUBOUT" and "C-H".
  406.  */
  407. backdel(f, n)
  408. {
  409.         register int    s;
  410.  
  411.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  412.         return(rdonly());    /* we are in read only mode    */
  413.         if (n < 0)
  414.                 return (forwdel(f, -n));
  415.         if (f != FALSE) {                       /* Really a kill.       */
  416.                 if ((lastflag&CFKILL) == 0)
  417.                         kdelete();
  418.                 thisflag |= CFKILL;
  419.         }
  420.         if ((s=backchar(f, n)) == TRUE)
  421.                 s = ldelete(n, f);
  422.         return (s);
  423. }
  424.  
  425. /*
  426.  * Kill text. If called without an argument, it kills from dot to the end of
  427.  * the line, unless it is at the end of the line, when it kills the newline.
  428.  * If called with an argument of 0, it kills from the start of the line to dot.
  429.  * If called with a positive argument, it kills from dot forward over that
  430.  * number of newlines. If called with a negative argument it kills backwards
  431.  * that number of newlines. Normally bound to "C-K".
  432.  */
  433. killtext(f, n)
  434. {
  435.         register int    chunk;
  436.         register LINE   *nextp;
  437.  
  438.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  439.         return(rdonly());    /* we are in read only mode    */
  440.         if ((lastflag&CFKILL) == 0)             /* Clear kill buffer if */
  441.                 kdelete();                      /* last wasn't a kill.  */
  442.         thisflag |= CFKILL;
  443.         if (f == FALSE) {
  444.                 chunk = llength(curwp->w_dotp)-curwp->w_doto;
  445.                 if (chunk == 0)
  446.                         chunk = 1;
  447.         } else if (n == 0) {
  448.                 chunk = curwp->w_doto;
  449.                 curwp->w_doto = 0;
  450.         } else if (n > 0) {
  451.                 chunk = llength(curwp->w_dotp)-curwp->w_doto+1;
  452.                 nextp = lforw(curwp->w_dotp);
  453.                 while (--n) {
  454.                         if (nextp == curbp->b_linep)
  455.                                 return (FALSE);
  456.                         chunk += llength(nextp)+1;
  457.                         nextp = lforw(nextp);
  458.                 }
  459.         } else {
  460.                 mlwrite("neg kill");
  461.                 return (FALSE);
  462.         }
  463.         return (ldelete(chunk, TRUE));
  464. }
  465.  
  466. /*
  467.  * Yank text back from the kill buffer. This is really easy. All of the work
  468.  * ms done by the standard insert routines. All you do is run the loop, and
  469.  * check for errors. Bound to "C-Y".
  470.  */
  471. yank(f, n)
  472. {
  473.         register int    c;
  474.         register int    i;
  475.         extern   int    kused;
  476.  
  477.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  478.         return(rdonly());    /* we are in read only mode    */
  479.         if (n < 0)
  480.                 return (FALSE);
  481.         while (n--) {
  482.                 i = 0;
  483.                 while ((c=kremove(i)) >= 0) {
  484.                         if (c == '\n') {
  485.                                 if (lnewline(FALSE, 1) == FALSE)
  486.                                         return (FALSE);
  487.                         } else {
  488.                                 if (linsert(1, c) == FALSE)
  489.                                         return (FALSE);
  490.                         }
  491.                         ++i;
  492.                 }
  493.         }
  494.         return (TRUE);
  495. }
  496.  
  497. setmode(f, n)    /* prompt and set an editor mode */
  498.  
  499. int f, n;    /* default and argument */
  500.  
  501. {
  502.     adjustmode(TRUE, FALSE);
  503. }
  504.  
  505. delmode(f, n)    /* prompt and delete an editor mode */
  506.  
  507. int f, n;    /* default and argument */
  508.  
  509. {
  510.     adjustmode(FALSE, FALSE);
  511. }
  512.  
  513. setgmode(f, n)    /* prompt and set a global editor mode */
  514.  
  515. int f, n;    /* default and argument */
  516.  
  517. {
  518.     adjustmode(TRUE, TRUE);
  519. }
  520.  
  521. delgmode(f, n)    /* prompt and delete a global editor mode */
  522.  
  523. int f, n;    /* default and argument */
  524.  
  525. {
  526.     adjustmode(FALSE, TRUE);
  527. }
  528.  
  529. adjustmode(kind, global)    /* change the editor mode status */
  530.  
  531. int kind;    /* true = set,        false = delete */
  532. int global;    /* true = global flag,    false = current buffer flag */
  533. {
  534.     register char prompt[50];    /* string to prompt user with */
  535.     register char *scan;        /* scanning pointer to convert prompt */
  536.     register int i;            /* loop index */
  537.     char cbuf[NPAT];        /* buffer to recieve mode name into */
  538.  
  539.     /* build the proper prompt string */
  540.     if (global)
  541.         strcpy(prompt,"Global mode to ");
  542.     else
  543.         strcpy(prompt,"Mode to ");
  544.  
  545.     if (kind == TRUE)
  546.         strcat(prompt, "add: ");
  547.     else
  548.         strcat(prompt, "delete: ");
  549.  
  550.     /* prompt the user and get an answer */
  551.  
  552.     mlreply(prompt, cbuf, NPAT - 1);
  553.  
  554.     /* make it uppercase */
  555.  
  556.     scan = cbuf;
  557.     while (*scan != 0) {
  558.         if (*scan >= 'a' && *scan <= 'z')
  559.             *scan = *scan - 32;
  560.         scan++;
  561.     }
  562.  
  563.     /* test it against the modes we know */
  564.  
  565.     for (i=0; i < NUMMODES; i++) {
  566.         if (strcmp(cbuf, modename[i]) == 0) {
  567.             /* finding a match, we process it */
  568.             if (kind == TRUE)
  569.                 if (global)
  570.                     gmode |= (1 << i);
  571.                 else
  572.                     curwp->w_bufp->b_mode |= (1 << i);
  573.             else
  574.                 if (global)
  575.                     gmode &= ~(1 << i);
  576.                 else
  577.                     curwp->w_bufp->b_mode &= ~(1 << i);
  578.             /* display new mode line */
  579.             if (global == 0)
  580.                 upmode();
  581.             mlerase();    /* erase the junk */
  582.             return(TRUE);
  583.         }
  584.     }
  585.  
  586.     mlwrite("No such mode!");
  587.     return(FALSE);
  588. }
  589.